{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "TF Lite Week 1 Exercise - Question",
      "version": "0.3.2",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pXX-pi1r6NfG",
        "colab_type": "text"
      },
      "source": [
        "# Module 1 Exercise - Question (Fashion MNIST)\n",
        "Train your own model and convert it to TFLite\n",
        "\n",
        "This notebook uses the [Fashion MNIST](https://github.com/zalandoresearch/fashion-mnist) dataset which contains 70,000 grayscale images in 10 categories. The images show individual articles of clothing at low resolution (28 by 28 pixels), as seen here:\n",
        "\n",
        "<table>\n",
        "  <tr><td>\n",
        "    <img src=\"https://tensorflow.org/images/fashion-mnist-sprite.png\"\n",
        "         alt=\"Fashion MNIST sprite\"  width=\"600\">\n",
        "  </td></tr>\n",
        "  <tr><td align=\"center\">\n",
        "    <b>Figure 1.</b> <a href=\"https://github.com/zalandoresearch/fashion-mnist\">Fashion-MNIST samples</a> (by Zalando, MIT License).<br/>&nbsp;\n",
        "  </td></tr>\n",
        "</table>\n",
        "\n",
        "Fashion MNIST is intended as a drop-in replacement for the classic [MNIST](http://yann.lecun.com/exdb/mnist/) dataset—often used as the \"Hello, World\" of machine learning programs for computer vision. The MNIST dataset contains images of handwritten digits (0, 1, 2, etc.) in a format identical to that of the articles of clothing we'll use here.\n",
        "\n",
        "This uses Fashion MNIST for variety, and because it's a slightly more challenging problem than regular MNIST. Both datasets are relatively small and are used to verify that an algorithm works as expected. They're good starting points to test and debug code.\n",
        "\n",
        "We will use 60,000 images to train the network and 10,000 images to evaluate how accurately the network learned to classify images. You can access the Fashion MNIST directly from TensorFlow. Import and load the Fashion MNIST data directly from TensorFlow:"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rjOAfhgd__Sp",
        "colab_type": "text"
      },
      "source": [
        "# Setup"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Bp_nvHnh_tDo",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!pip3 install -q tensorflow-gpu==2.0.0-beta1"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pfyZKowNAQ4j",
        "colab_type": "code",
        "outputId": "59f82f85-2ab9-433d-b371-270d2afc7c2a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "# TensorFlow and tf.keras\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "\n",
        "# Helper libraries\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "import pathlib\n",
        "from google.colab import files\n",
        "\n",
        "\n",
        "print(tf.__version__)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1.14.0-rc1\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tadPBTEiAprt",
        "colab_type": "text"
      },
      "source": [
        "# Download Fashion MNIST Dataset\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ds9gfZKzAnkX",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "splits = tfds.Split.ALL.subsplit(weighted=(80, 10, 10))\n",
        "\n",
        "splits, info = tfds.load('fashion_mnist', with_info=True, as_supervised=True, split=splits)\n",
        "\n",
        "(train_examples, validation_examples, test_examples) = splits\n",
        "\n",
        "num_examples = info.splits['train'].num_examples\n",
        "num_classes = info.features['label'].num_classes"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-eAv71FRm4JE",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "class_names = ['T-shirt_top', 'Trouser', 'Pullover', 'Dress', 'Coat',\n",
        "               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hXe6jNokqX3_",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "with open('labels.txt', 'w') as f:\n",
        "  f.write('\\n'.join(class_names))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "q0RxpwTmQN-y",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "IMG_SIZE = 28"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZAkuq0V0Aw2X",
        "colab_type": "text"
      },
      "source": [
        "# Preprocessing data"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_5SIivkunKCC",
        "colab_type": "text"
      },
      "source": [
        "## Preprocess"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nQMIkJf9AvJ4",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Write a function to normalize and resize the images\n",
        "\n",
        "def format_example(image, label):\n",
        "  # Cast image to float32\n",
        "  image = # YOUR CODE HERE\n",
        "  # Resize the image if necessary\n",
        "  image = # YOUR CODE HERE\n",
        "  # Normalize the image in the range [0, 1]\n",
        "  image = # YOUR CODE HERE\n",
        "  return image, label"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "oEQP743aMv4C",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Set the batch size to 32\n",
        "\n",
        "BATCH_SIZE = 32"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JM4HfIJtnNEk",
        "colab_type": "text"
      },
      "source": [
        "## Create a Dataset from images and labels"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zOL4gSUARFjM",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Prepare the examples by preprocessing the them and then batching them (and optionally prefetching them)\n",
        "\n",
        "# If you wish you can shuffle train set here\n",
        "train_batches = # YOUR CODE HERE\n",
        "\n",
        "validation_batches = # YOUR CODE HERE\n",
        "test_batches = # YOUR CODE HERE"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "M-topQaOm_LM",
        "colab_type": "text"
      },
      "source": [
        "# Building the model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4gsYqdIlEFVg",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "\"\"\"\n",
        "Model: \"sequential\"\n",
        "_________________________________________________________________\n",
        "Layer (type)                 Output Shape              Param #   \n",
        "=================================================================\n",
        "conv2d (Conv2D)              (None, 26, 26, 16)        160       \n",
        "_________________________________________________________________\n",
        "max_pooling2d (MaxPooling2D) (None, 13, 13, 16)        0         \n",
        "_________________________________________________________________\n",
        "conv2d_1 (Conv2D)            (None, 11, 11, 32)        4640      \n",
        "_________________________________________________________________\n",
        "flatten (Flatten)            (None, 3872)              0         \n",
        "_________________________________________________________________\n",
        "dense (Dense)                (None, 64)                247872    \n",
        "_________________________________________________________________\n",
        "dense_1 (Dense)              (None, 10)                650       \n",
        "=================================================================\n",
        "Total params: 253,322\n",
        "Trainable params: 253,322\n",
        "Non-trainable params: 0\n",
        "\"\"\""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kDqcwksFB1bh",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Build the model shown in the previous cell\n",
        "\n",
        "\n",
        "model = tf.keras.Sequential([\n",
        "  # Set the input shape to (28, 28, 1), kernel size=3, filters=16 and use ReLU activation,  \n",
        "  tf.keras.layers.Conv2D(# YOUR CODE HERE),    \n",
        "  tf.keras.layers.MaxPooling2D(),\n",
        "  # Set the number of filters to 32, kernel size to 3 and use ReLU activation \n",
        "  tf.keras.layers.Conv2D(# YOUR CODE HERE),\n",
        "  # Flatten the output layer to 1 dimension\n",
        "  tf.keras.layers.Flatten(),\n",
        "  # Add a fully connected layer with 64 hidden units and ReLU activation\n",
        "  tf.keras.layers.Dense(# YOUR CODE HERE),\n",
        "  # Attach a final softmax classification head\n",
        "  tf.keras.layers.Dense(# YOUR CODE HERE)])\n",
        "\n",
        "# Set the loss and accuracy metrics\n",
        "model.compile(\n",
        "    optimizer='adam', \n",
        "    loss=# YOUR CODE HERE, \n",
        "    metrics=# YOUR CODE HERE)\n",
        "      "
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zEMOz-LDnxgD",
        "colab_type": "text"
      },
      "source": [
        "## Train"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JGlNoRtzCP4_",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "model.fit(train_batches, \n",
        "          epochs=10,\n",
        "          validation_data=validation_batches)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TZT9-7w9n4YO",
        "colab_type": "text"
      },
      "source": [
        "# Exporting to TFLite"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9dq78KBkCV2_",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "export_dir = 'saved_model/1'\n",
        "\n",
        "# Use the tf.saved_model API to export the SavedModel\n",
        "\n",
        "# Your Code Here"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "EDGiYrBdE6fl",
        "colab_type": "code",
        "cellView": "form",
        "colab": {}
      },
      "source": [
        "#@title Select mode of optimization\n",
        "mode = \"Speed\" #@param [\"Default\", \"Storage\", \"Speed\"]\n",
        "\n",
        "if mode == 'Storage':\n",
        "  optimization = tf.lite.Optimize.OPTIMIZE_FOR_SIZE\n",
        "elif mode == 'Speed':\n",
        "  optimization = tf.lite.Optimize.OPTIMIZE_FOR_LATENCY\n",
        "else:\n",
        "  optimization = tf.lite.Optimize.DEFAULT"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SLskPWHsG4Nj",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "optimization"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RbcS9C00CzGe",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Use the TFLiteConverter SavedModel API to initialize the converter\n",
        "converter = # YOUR CODE HERE\n",
        "\n",
        "# Set the optimzations\n",
        "converter.optimizations = # YOUR CODE HERE\n",
        "\n",
        "# Invoke the converter to finally generate the TFLite model\n",
        "tflite_model = # YOUR CODE HERE"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "q5PWCDsTC3El",
        "colab_type": "code",
        "outputId": "966f63a7-a907-426a-8d06-38c9959efc4e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        }
      },
      "source": [
        "tflite_model_file = pathlib.Path('/content/model.tflite')\n",
        "tflite_model_file.write_bytes(tflite_model)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "258632"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 35
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SR6wFcQ1Fglm",
        "colab_type": "text"
      },
      "source": [
        "# Test if your model is working"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "O3IFOcUEIzQx",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Load TFLite model and allocate tensors.\n",
        "interpreter = tf.lite.Interpreter(model_content=tflite_model)\n",
        "interpreter.allocate_tensors()\n",
        "\n",
        "input_index = interpreter.get_input_details()[0][\"index\"]\n",
        "output_index = interpreter.get_output_details()[0][\"index\"]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rKcToCBEC-Bu",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Gather results for the randomly sampled test images\n",
        "predictions = []\n",
        "test_labels = []\n",
        "test_images = []\n",
        "\n",
        "for img, label in test_batches.take(50):\n",
        "  interpreter.set_tensor(input_index, img)\n",
        "  interpreter.invoke()\n",
        "  predictions.append(interpreter.get_tensor(output_index))\n",
        "  test_labels.append(label[0])\n",
        "  test_images.append(np.array(img))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kSjTmi05Tyod",
        "colab_type": "code",
        "cellView": "form",
        "colab": {}
      },
      "source": [
        "#@title Utility functions for plotting\n",
        "# Utilities for plotting\n",
        "\n",
        "def plot_image(i, predictions_array, true_label, img):\n",
        "  predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]\n",
        "  plt.grid(False)\n",
        "  plt.xticks([])\n",
        "  plt.yticks([])\n",
        "  \n",
        "  img = np.squeeze(img)\n",
        "\n",
        "  plt.imshow(img, cmap=plt.cm.binary)\n",
        "\n",
        "  predicted_label = np.argmax(predictions_array)\n",
        "  if predicted_label == true_label.numpy():\n",
        "    color = 'green'\n",
        "  else:\n",
        "    color = 'red'\n",
        "    \n",
        "  plt.xlabel(\"{} {:2.0f}% ({})\".format(class_names[predicted_label],\n",
        "                                100*np.max(predictions_array),\n",
        "                                class_names[true_label]),\n",
        "                                color=color)\n",
        "\n",
        "def plot_value_array(i, predictions_array, true_label):\n",
        "  predictions_array, true_label = predictions_array[i], true_label[i]\n",
        "  plt.grid(False)\n",
        "  plt.xticks(list(range(10)))\n",
        "  plt.yticks([])\n",
        "  thisplot = plt.bar(range(10), predictions_array[0], color=\"#777777\")\n",
        "  plt.ylim([0, 1])\n",
        "  predicted_label = np.argmax(predictions_array[0])\n",
        "\n",
        "  thisplot[predicted_label].set_color('red')\n",
        "  thisplot[true_label].set_color('blue')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ZZwg0wFaVXhZ",
        "colab_type": "code",
        "outputId": "86a178e9-4c5b-4f9e-ebcb-556dd2f57e8b",
        "cellView": "both",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 214
        }
      },
      "source": [
        "#@title Visualize the outputs { run: \"auto\" }\n",
        "index = 49 #@param {type:\"slider\", min:1, max:50, step:1}\n",
        "plt.figure(figsize=(6,3))\n",
        "plt.subplot(1,2,1)\n",
        "plot_image(index, predictions, test_labels, test_images)\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWQAAADFCAYAAABjLIjfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAEm9JREFUeJzt3XmUJWV5x/HvwywwLLJDBhgciDog\nLsAQxEgIiWCURWM0gksQjGg8RJMoqNEgUU8UCccD5gQjWxSCCIgCxy1KjAEMoAwuoCCyDIiswybr\nMD08+aNqSE/XW933ztYv9vdzzj19+5n3rapbDb9bt9636kZmIkmafGtN9gZIkhoGsiRVwkCWpEoY\nyJJUCQNZkiphIEtSJQxkSaqEgSxJlTCQJakS0yd7A6TJttlmm+XcuXMnezM0gZ/8BEZGBms7fTq8\n+MWrd3sGtWDBgkWZufkgbQ1kTXlz587lqquumuzN0AQiBm87MgK1/Ekj4tZB23rKQpIqYSBLUiUM\nZEmqxFDnkB380Oq0cOFCFi1aNMSZQum3y1CB7OCHVqfddtttsjdBmlSespCkShjIklQJA1mSKmEg\nS1IlDGRJqoSBLEmVMJAlqRIGsiRVwkCWpEoYyJJUCQNZkiphIEtSJQxkSaqEgSxJlTCQJakSBrIk\nVcJAlqRKGMiSVAkDWZIqYSBLUiUMZEmqhIEsSZUwkCWpEgayJFXCQJakShjIklQJA1mSKmEgS1Il\nDGRJqoSBLEmVMJAlqRIGsiRVwkCWpEoYyJJUCQNZkiphIEtSJQxkSaqEgSxJlTCQJakSBrIkVcJA\nlqRKTJ/sDdD43vWud3VqF1xwQbHtzTff3KnNmjWr2Hbp0qWd2lprld+fI6JTy8yB20oajEfIklQJ\nA1mSKmEgS1IlDGRJqsSUG9RbXYNRH/vYxzq1Sy+9tNj28MMP79Q+8IEPFNtuueWWndqGG25YbHvM\nMcd0ascdd1yxbWlQb9q0acW2JX3768ILL+zUHn/88WLbgw8+eOD1SVOBR8iSVAkDWZIqYSBLUiUM\nZEmqhIEsSZWYcrMsVsWlvfvtt1+n9v3vf79TmzNnTrH/EUcc0aktWrSo2HbGjBmd2pIlS4ptb7/9\n9mK9ZObMmQO3Lbn11luL9aOPPrpTe+ihh4ptX/va1y73e98MGGmq8AhZkiphIEtSJQxkSaqEgSxJ\nlZhyg3p9brvttk5t2223LbZ98MEHO7XSJc6LFy8u9n/Ri17Uqd10003Ftg8//HCn1jcgd84553Rq\nu+yyS7HtUUcdVawP6sgjjyzWt9pqq05tp512KrYd+zq8l7KmOo+QJakSBrIkVcJAlqRKGMiSVAkD\nWZIqUcUsi9KlwH03S+/7ZuSSBQsWdGp77rlnse3aa6/dqe24447FtldccUWnNm/evE6t75Lh0oyK\nvm+HLs08eOqpp4ptN998806t7wb1J554YqdWuiQc4JJLLunU+maQbL311p3aHXfcUWx73333Lff7\nyMhIsZ00VXiELEmVMJAlqRIGsiRVwkCWpEoMPai3Ou5ZW7rn76pw7LHHdmqbbrppse3666/fqfXd\no3j77bfv1DbeeONObYMNNij2f/TRRzu1vv06zP2QSwOAfQNlYwfUAE455ZRi22E873nP69Se9axn\nFdueccYZE26TNJV4hCxJlTCQJakSBrIkVcJAlqRKrPSVeqvrHrbXXnttsX788cd3ahdeeGGx7Sab\nbNKp9Q2I3XvvvZ1aaaCvzw033NCp3X///QP3XxXWW2+9Tm3nnXcutt1nn306tQMPPLDYdv78+Su1\nXddff32xPvYqwscff3yl1iM903mELEmVMJAlqRIGsiRVwkCWpEoYyJJUiaFnWQw6q6J0z9/zzjuv\n2LZ0v91bbrml2Hbp0qWd2uzZs4ttS/dU7rtMu7TcG2+8sdi25IUvfGGntu+++xbblu6zXLrkuK9t\n38yJlVXaBwDnnntup9b3t7zssss6tbvuuqvY9qCDDlru9777PEtThUfIklQJA1mSKmEgS1IlDGRJ\nqsRK3w/5fe97X7HdxRdf3Kn1felnaTBno402KrZdZ511OrW+QaPScvsunS5t2+mnn15se9hhhxXr\na8pjjz1WrB999NGd2plnnllsW7pUfBilL4WF8r2PS198CvDAAw8s93vfoKI0VXiELEmVMJAlqRIG\nsiRVwkCWpEoYyJJUiaFmWSxZsoQ777xzudr+++9fbPumN72pU+ubHXDPPfd0an2X0ZZmQ/TNGLj7\n7rs7tYULFxbbjr1ZOsC8efOKbUvbVvom6b7LtJ944olOre+bmc8666xO7b3vfW+xbemy9t13373Y\ntvTa+mZDlL6pu2+WxbrrrtupPfnkk8W2c+fOXe73Qw45pNhOmio8QpakShjIklQJA1mSKmEgS1Il\n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\n",
            "text/plain": [
              "<Figure size 432x216 with 2 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "076bo3FMpRDb",
        "colab_type": "text"
      },
      "source": [
        "# Download TFLite model and assets"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "XsPXqPlgZPjE",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "files.download(tflite_model_file)\n",
        "files.download('labels.txt')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VyBVNwAzH3Oe",
        "colab_type": "text"
      },
      "source": [
        "# Deploying TFLite model"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pdfa5L6wH87u",
        "colab_type": "text"
      },
      "source": [
        "Now once you've the trained TFLite model downloaded, you can ahead and deploy this on an Android/iOS application by placing the model assets in the appropriate location."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iLY6X8P90L0P",
        "colab_type": "text"
      },
      "source": [
        "# Prepare the test images for download (Optional)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "G3bjzLj10OJv",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!mkdir -p test_images"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "pVrBZv1-0Py-",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from PIL import Image\n",
        "\n",
        "for index, (image, label) in enumerate(test_batches.take(50)):\n",
        "  image = tf.cast(image * 255.0, tf.uint8)\n",
        "  image = tf.squeeze(image).numpy()\n",
        "  pil_image = Image.fromarray(image)\n",
        "  pil_image.save('test_images/{}_{}.jpg'.format(class_names[label[0]].lower(), index))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nX0N0M8u0R2s",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!ls test_images"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LvLht1QM0W8k",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!zip -qq fmnist_test_images.zip -r test_images/"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "FdOq-4sT0X95",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "files.download('fmnist_test_images.zip')"
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}